package com.tms.control;

import com.github.pagehelper.PageInfo;
import com.tms.domain.*;
import com.tms.domain.req.BillReq;
import com.tms.quartz.service.QuartzService;
import com.tms.service.*;
import com.tms.utils.Data;
import com.tms.utils.JsonResult;
import com.tms.utils.description.DescriptionService;
import com.tms.utils.excel.ExcelUtils;
import com.tms.utils.image.ImageService;
import com.tms.utils.token.TokenService;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.ParseException;

import static com.tms.core.constants.BillConstants.*;
import static com.tms.core.constants.StatusConstants.*;

import java.util.*;

/**
 * 采购记录
 */
@RestController
@RequestMapping("/api/bills")
public class BillController extends BaseController {

    @Autowired
    private BillService billService;

    @Autowired
    private BillStatusService billStatusService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private ImageService imageService;

    @Autowired
    private LocationService locationService;

    @Autowired
    private QuartzService quartzService;

    @Autowired
    private ToolService toolService;

    @Autowired
    private ToolStatusService toolStatusService;

    @Autowired
    private ToolDefService toolDefService;

    @Autowired
    private LifeCycleStatusService lifeCycleStatusService;

    @Autowired
    private LifeCycleService lifeCycleService;

    @Autowired
    private DescriptionService descriptionService;

    private com.tms.utils.DateUtil dateUtil = new com.tms.utils.DateUtil();

    private static final String DEFAULT_IMAGE_URL = "/model/default.png";

    private static final int MIN_LENGTH_IMG = 7;

    /**
     * 提交采购订单
     *
     * @param req      HttpServletRequest获取token从而获取用户
     * @param code     模具code
     * @param name     模具名称
     * @param family   模具familyName
     * @param image    模具图片文件
     * @param count    模具数量
     * @param model    模具模型名称
     * @param partNo   模具partNo
     * @param usedFor  模具用途
     * @param upl      模具upl
     * @param pmPeriod 模具pmPeriod
     * @param remark   模具remark
     * @param locationName 模具位置
     * @return 成功返回订单信息，失败返回错误信息
     */
    @PostMapping
    public JsonResult submitBill(HttpServletRequest req, @RequestParam(value = "code") String code, @RequestParam(value = "name") String name,
                                 @RequestParam(value = "family") String family, @RequestParam(value = "image") MultipartFile image,
                                 @RequestParam(value = "count") int count, @RequestParam(value = "model") String model,
                                 @RequestParam(value = "partNo") String partNo, @RequestParam(value = "usedFor") String usedFor,
                                 @RequestParam(value = "upl") int upl, @RequestParam(value = "pmPeriod") int pmPeriod,
                                 @RequestParam(value = "remark") String remark, @RequestParam(value = "location") String locationName) {
        JsonResult jsonResult;
        //随机生成
        String billNo = dateUtil.getBillNo();
        //找到提交者
        //tokenService.getUserByRequest(request)
        User submitPerson = tokenService.getUserByRequest(req);
        if (submitPerson == null) {
            return new JsonResult(ERROR_NULL_USER.getStatus(), ERROR_NULL_USER.getDesc());
        }
        int workcellId = submitPerson.getWorkcell().getId();
        int familyId = toolDefService.findFamilyIdByName(family);
        //找到location
        Location location = locationService.findLocationByName(locationName, workcellId);
        if (location == null) {
            return new JsonResult(ERROR_NULL_LOCATION.getStatus(), ERROR_NULL_LOCATION.getDesc());
        }
        //确定提交时间
        Date submitTime;
        try {
            submitTime = dateUtil.getCurrentDate();
        } catch (ParseException e) {
            e.printStackTrace();
            return new JsonResult(ERROR_PARSE_DATE.getStatus(), ERROR_PARSE_DATE.getDesc());
        }
        //文件路径
        String imageUrl = imageService.getName(image, workcellId, "Bill");
        if (imageUrl == null || imageUrl.length() < MIN_LENGTH_IMG) {
            imageUrl = DEFAULT_IMAGE_URL;
        }
        //构造BillResponse
        BillReq billReq = new BillReq(null, familyId, family, null, code, null, billNo, name, model,
                partNo, usedFor, upl, pmPeriod, remark, workcellId, submitPerson.getId(), submitTime, null,
                null, null, null, imageUrl, BILL_JUST_SUBMIT.getStatus(), false, count, location.getId());
        //写入
        billService.create(billReq);
        //封装返回报文
        jsonResult = new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(billReq));
        return jsonResult;
    }

    /**
     * 分页查看bill记录(入库记录)
     *
     * @param page     页数
     * @param pageSize 每页个数
     * @param status   状态
     * @return 成功查询返回bill订单的list，失败返回错误信息
     * @author Liao
     */
    @GetMapping
    public JsonResult viewBills(@RequestParam(value = "page", defaultValue = "1") int page, @RequestParam(value = "pageSize", defaultValue = "5") int pageSize,
                                @RequestParam(value = "status", defaultValue = "-1") int status, HttpServletRequest request) {
        int workcellId = tokenService.getWorkcellId(request);
        if (workcellId == 0) {
            return new JsonResult(ERROR_TOKEN.getStatus(), ERROR_TOKEN.getDesc());
        }
        PageInfo<BillResponse> info = billService.findAlls(page, pageSize, status, workcellId);
        return new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data("bills", info));
    }

    /**
     * 通过id准确查找bill(入库记录)
     *
     * @param id bill的id
     * @return 成功返回对应id的bill订单信息，失败返回错误信息
     * @author Liao
     */
    @GetMapping("{id}")
    public JsonResult viewBill(@PathVariable(value = "id") int id, HttpServletRequest request) {
        User user = tokenService.getUserByRequest(request);
        if (user == null) {
            return new JsonResult(ERROR_TOKEN.getStatus(), ERROR_TOKEN.getDesc());
        }
        BillResponse bill = billService.findById(id);
        if (bill == null) {
            return new JsonResult(ERROR_NULL_BILL.getStatus(), ERROR_NULL_BILL.getDesc());
        } else if (bill.getWorkcell().getId() == user.getWorkcell().getId()) {
            return new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(bill));
        } else {
            return new JsonResult(ERROR_OTHER_WORKCELL.getStatus(), ERROR_OTHER_WORKCELL.getDesc());
        }
    }


    @GetMapping("/download")
    public void download(HttpServletResponse response) {
        String dataDirectory = System.getProperty("user.home") + "/tms/model";
        String fileName = "model.xlsx";
        File file = new File(dataDirectory, fileName);
        if (file.exists()) {
            response.setContentType("application/vnd.ms-excel");
            response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            } catch (IOException ex) {
                //处理异常
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException ignored) {
                    }
                }
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException ignored) {
                    }
                    try {
                        fis.close();
                    } catch (IOException ignored) {
                    }
                }
            }
        }
    }


    /**
     * 以Excel的形式提交采购订单
     * @param excel 订单Excel文件
     * @param images 对应图片文件
     * @param request HttpServletRequest 获取用户
     * @return 成功返回订单信息，失败返回错误信息
     * @throws IOException Excel文件转换错误
     * @throws ParseException Excel文件转换错误
     */
    @PostMapping("/uploadExcel")
    public JsonResult uploadExcel(@RequestParam("excel") MultipartFile excel, @RequestParam("images") List<MultipartFile> images,
                                  HttpServletRequest request) throws IOException, ParseException {
        User submitPerson = tokenService.getUserByRequest(request);
        if (submitPerson == null) {
            return new JsonResult(ERROR_TOKEN.getStatus(), ERROR_TOKEN.getDesc());
        }
        List<BillExcel> bills = ExcelUtils.importExcel(excel, BillExcel.class);
        List<BillReq> reqs = new ArrayList<>();
        HashMap<String, MultipartFile> map = new HashMap<>(images.size());
        for (MultipartFile multipartFile : images) {
            String name = multipartFile.getOriginalFilename();
            map.put(Objects.requireNonNull(name).substring(0, name.lastIndexOf('.')), multipartFile);
        }
        for (BillExcel billExcel : bills) {
            //确定提交时间
            Date submitTime = dateUtil.getCurrentDate();
            //随机生成
            String billNo = dateUtil.getBillNo();
            //图片路径
            String imgPath = imageService.getName(map.get(billExcel.getCode()), submitPerson.getWorkcell().getId(), "Bill");
            if (imgPath == null || imgPath.length() < 10) {
                imgPath = DEFAULT_IMAGE_URL;
            }
            Location location = locationService.findLocationByName(billExcel.getLocation(), submitPerson.getWorkcell().getId());
            if (location == null) {
                return new JsonResult(ERROR_NULL_LOCATION.getStatus(), ERROR_NULL_LOCATION.getDesc());
            }
            //构造BillResponse
            BillReq billReq = new BillReq(null, toolDefService.findFamilyIdByName(billExcel.getFamily()), billExcel.getFamily(),
                    null, billExcel.getCode(), null, billNo, billExcel.getName(), billExcel.getModel(),
                    billExcel.getPartNo(), billExcel.getUsedFor(), billExcel.getUpl(), billExcel.getPmPeriod(),
                    billExcel.getRemark(), submitPerson.getWorkcell().getId(), submitPerson.getId(), submitTime,
                    null, null, null, null, imgPath, BILL_JUST_SUBMIT.getStatus(),
                    false, billExcel.getCount(), location.getId());
            //写入
            billService.create(billReq);
            reqs.add(billReq);
        }
        return new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(reqs, "billReqs"));
    }


    /**
     * 初审采购入库申请
     *
     * @param map 参数map
     * @param id  bill订单id
     * @param req HttpServletRequest 获取用户
     * @return 成功返回订单处理信息，失败返回错误信息
     * @author Lisa
     * @date 2020年6月28日15:12:26
     */
    @PatchMapping("/{id}/firstCheck")
    public JsonResult firstCheckBill(@RequestBody Map<String, String> map, @PathVariable int id, HttpServletRequest req) {
        //判断Token
        User user = tokenService.getUserByRequest(req);
        //如果没有这个人
        if (user == null) {
            return new JsonResult(ERROR_TOKEN.getStatus(), ERROR_TOKEN.getDesc());
        }
        BillResponse billResponse = billService.findById(id);
        if (billResponse == null) {
            return new JsonResult(ERROR_NULL_BILL.getStatus(), ERROR_NULL_BILL.getDesc());
        } else if (billResponse.getWorkcell().getId() != user.getWorkcell().getId()) {
            return new JsonResult(ERROR_OTHER_WORKCELL.getStatus(), ERROR_OTHER_WORKCELL.getDesc());
        }
        int statusId = Integer.parseInt(map.get("status"));
        // 判断status 是不是之前已经执行了的 或者 status 是不是终止状态
        // 如果是执行的话返回报错
        if (statusId <= billResponse.getStatus().getId()
                || billResponse.getStatus().getId() == BILL_FAILED_FIRST.getStatus()
                || billResponse.getStatus().getId() == BILL_FAILED_SECOND.getStatus()
                || billResponse.getStatus().getId() == BILL_SUCCESS_SECOND.getStatus()
                || (statusId == BILL_SUCCESS_SECOND.getStatus() && billResponse.getStatus().getId() == BILL_JUST_SUBMIT.getStatus())) {
            return new JsonResult(ERROR_REPEAT_STATUS.getStatus(), ERROR_REPEAT_STATUS.getDesc());
        }
        Date currentTime;
        try {
            currentTime = dateUtil.getCurrentDate();
        } catch (ParseException e) {
            e.printStackTrace();
            return new JsonResult(ERROR.getStatus(), ERROR.getDesc());
        }
        switch (statusId) {
            case 0:
                return new JsonResult(ERROR_NULL_STATUS.getStatus(), ERROR_NULL_STATUS.getDesc());
            case 1:
            case 2:
                billResponse.setFirstTime(currentTime);
                billResponse.setFirstPerson(user);
                break;
            case 3:
                billResponse.setSecondTime(currentTime);
                billResponse.setSecondPerson(user);
                break;
            case 4:
                billResponse.setSecondTime(currentTime);
                billResponse.setSecondPerson(user);
                addToolAndMailJob(billResponse, user);
                break;
            default:
                return new JsonResult(ERROR_STATUS.getStatus(), ERROR_STATUS.getDesc());
        }
        Status billStatus = billStatusService.findById(statusId);
        billResponse.setStatus(billStatus);
        billService.updateStatusById(billResponse);
        return new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(billResponse));
    }

    /**
     * 终审采购入库申请
     *
     * @param map 参数map
     * @param id bill订单id
     * @param req HttpServletRequest 获取用户
     * @return 成功返回订单处理信息，失败返回错误信息
     * @author Lisa
     * @date 2020年6月30日20:11:26
     */
    @PatchMapping("/{id}/secondCheck")
    public JsonResult secondCheckBill(@RequestBody Map<String, String> map, @PathVariable int id, HttpServletRequest req) {
        return firstCheckBill(map, id, req);
    }

    private void addToolAndMailJob(BillResponse billResponse, User manager) {
        TDef tDef = toolDefService.findToolDefByCode(billResponse.getCode());
        if (tDef == null) {
            tDef = new TDef(billResponse.getCode(), billResponse.getName(), billResponse.getFamilyId(), billResponse.getFamilyName(),
                    billResponse.getModel(), billResponse.getPartNo(), billResponse.getSubmitPerson(), manager, null,
                    billResponse.getUsedFor(), billResponse.getUpl(), billResponse.getPmPeriod(), billResponse.getSecondTime(),
                    null, billResponse.getRemark(), billResponse.getWorkcell(), billResponse.getCount());
        }
        Status status = toolStatusService.findById(TOOL_INDOOR.getStatus());
        int maxSeqId = toolService.getMaxSeqIdByCode(billResponse.getCode());
        for (int i = 1; i <= billResponse.getCount(); i++) {
            // 添加tool
            Tool tool = new Tool(billResponse.getCode(), 0.0, maxSeqId + i, billResponse.getSecondTime(),
                    0, billResponse.getBillNo(), billResponse.getImage(), billResponse.getLocation(), tDef, status);
            toolService.createTool(tool);
            if (tool.getId() == 0) {
                return;
            }

            // 创建lifeCycle
            Status lifeCycleStatus = lifeCycleStatusService.findById(LIFE_BILL.getStatus());
            LifeCycle lifeCycle = new LifeCycle(tool, lifeCycleStatus, billResponse.getId(), billResponse.getSecondTime(),
                    descriptionService.getDescription(billResponse));
            lifeCycleService.createLifeCycle(lifeCycle);

            // 添加job
            Map<String, String> map = new HashMap<>(1);
            map.put("toolId", String.valueOf(tool.getId()));
            try {
                quartzService.addJobToTrigger(tool, 2, 20, map);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }

    }
}